import { selectDevice } from "@/utils/react";
import { decode } from "cbor-x";

const baseURL = `${window.location.origin}/api`;

export const HEADER_DEVICE_INFO = "device_token";
export const HEADER_PUSH_EC = "push_ec";
export const HEADER_PUSH_REQ = "push_req";

export interface Resp2 {
    header: Headers,
    body: Uint8Array<ArrayBuffer>,
}

function makeUrl(url: string) {
    return `${baseURL}${url}`;
}

async function fetch2(url: string, init: RequestInit) {
    const url2 = makeUrl(url);
    const resp = await fetch(url2, init);
    return await assertResp(resp);
}

export type Method = 'POST' | 'GET';

export async function serverFetch(url: string, method: Method, body: Uint8Array<ArrayBuffer> | null = null) {
    return await fetch2(url, {
        method,
        body
    });
}

export async function serverFetch2(url: string, method: Method, deviceId: number, body: Uint8Array<ArrayBuffer> | null = null) {
    return await fetch2(url, {
        method,
        body,
        headers: {
            'device_token': `${deviceId}`
        }
    });
}

export async function deviceFetch(url: string, method: Method, body: Uint8Array<ArrayBuffer> | null = null) {
    const current = selectDevice.value;
    if (current == null) {
        throw '没有选择任何设备';
    }
    const res = await fetch2(url, {
        method,
        body,
        headers: {
            'device_token': `${current.id}`
        }
    });
    return res;
}

export interface ErrInfo {
    err_code: number,
    err_msg: string,
}

async function assertResp(resp: Response) {
    if (resp.status != 200) {
        throw `错误:${resp.statusText}`
    }
    const buf = new Uint8Array(await resp.arrayBuffer());
    const respInfo = resp.headers.get('resp');
    if (respInfo == "ok") {
        let resp2: Resp2 = {
            header: resp.headers,
            body: buf
        };
        return resp2;
    }
    if (respInfo == "err") {
        const errInfo = decode(buf) as ErrInfo;
        throw `错误:${errInfo.err_code} => ${errInfo.err_msg}`;
    }
    throw `服务器异常`;
}

export function serverUpload(url: string, data: Uint8Array<ArrayBuffer>, cb: (prog: string) => void) {
    return new Promise<Uint8Array>((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open('POST', makeUrl(url));
        xhr.responseType = 'arraybuffer';
        xhr.upload.onprogress = (event) => {
            if (event.lengthComputable) {
                cb((event.loaded * 100 / event.total).toFixed(2));
            }
        };
        xhr.onload = () => {
            const respHead = xhr.getResponseHeader('resp');
            if (xhr.status != 200) {
                reject(xhr.statusText);
                return;
            }
            if (respHead == null) {
                reject('no resp head');
                return;
            }
            const respData = new Uint8Array(xhr.response);
            if (respHead == 'ok') {
                resolve(respData);
                return
            } else if (respHead == 'err') {
                const errInfo = decode(respData) as ErrInfo;
                reject(`错误:${errInfo.err_code} => ${errInfo.err_msg}`);
                return;
            } else {
                reject('服务器异常');
            }
        };
        xhr.onerror = reject;
        xhr.send(data);
    });
}
